class IUP_TOGGLE
-- Creates the toggle interface element. It is a two-state (on/off) button 
-- that, when selected, generates an action that activates a function in the 
-- associated application. Its visual representation can contain a text or an 
-- image.
--
-- Toggle with image or text can not change its behavior after mapped. This is 
-- a creation attribute. But after creation the image can be changed for 
-- another image, and the text for another text.
--
-- Toggles are activated using the Space key.
--
-- To build a set of mutual exclusive toggles, insert them in an IUP_RADIO 
-- container. They must be inserted before creation, and their behavior can not 
-- be changed. If you need to dynamically remove toggles that belongs to a 
-- radio in Windows, then put the radio inside an IUP_FRAME that has a title.
--
-- A toggle that is a child of an IUP_RADIO automatically receives a name when 
-- its is mapped into the native system.

inherit
	IUP_BUTTON
		redefine
			execute_map,
			execute_unmap,
			execute_destroy,
			execute_getfocus,
			execute_killfocus,
			execute_enterwindow,
			execute_leavewindow,
			execute_k_any,
			execute_help,
			execute_action_fni,
			execute_valuechanged
		end
	IUP_WIDGET_IGNORERADIO
	IUP_WIDGET_TOGGLE

create {ANY}
	toggle

feature {ANY}

	toggle (title: STRING)
		-- A new toggle. title is the text to be shown on the toggle. It can be 
		-- Void. It will set the TITLE attribute.
		local
			a_toggle, p: POINTER
		do
			if title /= Void then
				a_toggle := int_toggle(title.to_external, p)
			else
				a_toggle := int_toggle(p, p)
			end
			
			set_widget(a_toggle)
		end

	-- Attributes

	is_radio: BOOLEAN
		-- (read-only): returns if the toggle is inside a radio. Valid only after 
		-- the element is mapped.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "RADIO")
			Result := yesno_to_boolean(str)
		end

	set_right_button (state: BOOLEAN)
		-- (Windows Only) (creation only): place the check button at the right of 
		-- the text. Default: "False".
		do
			iup_open.set_attribute(Current, "RIGHTBUTTON", boolean_to_yesno(state))
		end

	set_value (value: STRING)
		-- (non inheritable): Toggle's state. Values can be "ON" or "OFF". If 
		-- 3state=True then can also be "NOTDEF". Default: "OFF". In GTK if you 
		-- change the state of a radio, the unchecked toggle will receive an 
		-- ACTION callback notification. Can only be set to "ON" for a toggle 
		-- inside a radio, it will automatically set to OFF the previous toggle 
		-- that was ON.
		require
			is_valid_state (value)
		do
			iup_open.set_attribute(Current, "VALUE", value)
		end

	get_value: STRING
		do
			Result := iup_open.get_attribute(Current, "VALUE")
		end

	set_3state (state: BOOLEAN)
		-- (creation only): Enable a three state toggle. Valid for toggles with 
		-- text only and that do not belong to a radio. Default: "False".
		do
			iup_open.set_attribute(Current, "3STATE", boolean_to_yesno(state))
		end

	-- Operations

	invert
		-- Invert the current state.
		do
			iup_open.set_attribute(Current, "VALUE", "TOGGLE")
		end

	-- Callbacks
	set_cb_toggle (act: FUNCTION[TUPLE[IUP_TOGGLE, INTEGER], STRING])
		-- Action generated when the toggle's state (on/off) was changed. The 
		-- callback also receives the toggle's state.
		--
		-- ih: identifier of the element that activated the event.
		-- state: 1 if the toggle's state was shifted to on; 0 if it was shifted 
		-- to off.
		--
		-- Returns: IUP_CLOSE will be processed.
		local
			operation: INTEGER
		do
			cb_action_fni := act

			if cb_action_fni /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ACTION", "Fn", operation)
		end

	set_cb_value_changed (act: FUNCTION[TUPLE[IUP_TOGGLE], STRING])
		-- Called after the value was interactively changed by the 
		-- user. Called after the ACTION callback, but under the same context. 
		local
			operation: INTEGER
		do
			cb_valuechanged := act

			if cb_valuechanged /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "VALUECHANGED_CB", "NONEEDED", operation)
		end

feature {IUP}

	-- Common callbacks
	
	execute_map: STRING
		do
			Result := cb_map.item([Current])
		end

	execute_unmap: STRING
		do
			Result := cb_unmap.item([Current])
		end

	execute_destroy: STRING
		do
			Result := cb_destroy.item([Current])
		end

	execute_getfocus: STRING
		do
			Result := cb_getfocus.item([Current])
		end

	execute_killfocus: STRING
		do
			Result := cb_getfocus.item([Current])
		end

	execute_enterwindow: STRING
		do
			Result := cb_enterwindow.item([Current])
		end

	execute_leavewindow: STRING
		do
			Result := cb_leavewindow.item([Current])
		end

	execute_k_any (c: INTEGER): STRING
		do
			Result := cb_k_any.item([Current, c])
		end

	execute_help
		do
			cb_help.call([Current])
		end

	-- Extra

	execute_action_fni (state: INTEGER): STRING
		do
			Result := cb_action_fni.item([Current, state])
		end

	execute_valuechanged: STRING
		do
			Result := cb_valuechanged.item([Current])
		end

feature {}

	-- For callbacks

	cb_action_fni: FUNCTION[TUPLE[IUP_TOGGLE, INTEGER], STRING]
	cb_valuechanged: FUNCTION[TUPLE[IUP_TOGGLE], STRING]

	-- Internals
	
	int_toggle (title: POINTER; action: POINTER): POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupToggle"
         }"
      end

	-- Validations

	is_valid_state (value: STRING): BOOLEAN
		do
			if value.is_equal("ON") or
				value.is_equal("OFF") or
				value.is_equal("NOTDEF") then
				Result := True
			else
				Result := False
			end
		end

end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2017, 2019, 2022 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
